import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:winkai/db/dao/msg_dao.dart';
import 'package:winkai/entity/chat_msg.dart';
import 'package:winkai/entity/msg_constant.dart';
import 'package:winkai/entity/role_info.dart';
import 'package:winkai/entity/subscribe_from.dart';
import 'package:winkai/ext/ext.dart';
import 'package:winkai/helper/chat_helper.dart';
import 'package:winkai/helper/iap/iap_helper.dart';
import 'package:winkai/helper/msg_helper.dart';
import 'package:winkai/helper/msg_receive_helper.dart';
import 'package:winkai/helper/user_helper.dart';
import 'package:winkai/main.dart';
import 'package:winkai/route/route_manifest.dart';
import 'package:winkai/service/msg_service.dart';
import 'package:winkai/service/ses_service.dart';
import 'package:winkai/utils/async_task_utils.dart';
import 'package:winkai/utils/listerer.dart';
import 'package:winkai/utils/page_jump_utils.dart';
import 'package:winkai/utils/smart_dialog.dart';
import 'package:winkai/widget/empty_layout.dart';
import 'package:winkai/widget/option_dialog.dart';

class ChatController extends GetxController {
  final random = Random(1);
  final Dispose _dispose = Dispose();
  final _asyncTask = AsyncTaskUtils();
  late String sessionId;
  late RoleInfo roleInfo;
  EmptyType? emptyType = EmptyType.loading;
  bool isDispose = false;

  var messageList = <ChatMsg>[].obs;
  var newChatNum = 0.obs;
  var autoScrollBottom = true.obs; //自动滚动
  var isScroll = false.obs;

  ChatController(this.sessionId, this.roleInfo);

  @override
  void onInit() {
    super.onInit();
    _initListener();
    getHistoryMsg();
  }

  void _initListener() {
    _dispose.add(MsgHelper().listen((p0) {
      var sessionId = p0.$2.msg.sessionId;
      if (this.sessionId == sessionId) {
        if (p0.$1 == MsgEvent.add) {
          _addMsg(p0.$2);
        } else if (p0.$1 == MsgEvent.update) {
          _updateMsg(p0.$2);
        } else if (p0.$1 == MsgEvent.remove) {
          _removeMsg(p0.$2);
        }
      }
    }));
  }

  void getHistoryMsg() async {
    var res = await getIt<MsgService>().getMsgList(sessionId);
    emptyType = null;
    update();
    if (res.isNotEmpty) {
      var list = res
          .map((e) => _messageInfoConvertChatMsg(e))
          .toList()
          .reversed
          .toList();
      messageList.addAll(list);
      var chatMsg = messageList.first;

      MsgReceiveHelper().checkMsgReplay(chatMsg.messageInfo);
    } else {
      var userId = getIt<SesService>().getUserIdBySessionId(sessionId);
      var greetings = roleInfo.greetings.randomOrNull;
      if (greetings?.isNotEmpty == true) {
        await getIt<MsgService>().insertOrUpdateMsg(
          greetings ?? '',
          userId: userId,
          sessionId: sessionId,
          status: MsgStatus.sended,
          contentType: MsgContentType.text,
        );
      }
    }
  }

  ChatMsg _messageInfoConvertChatMsg(MsgInfo msgInfo) {
    int type;
    var contentType = msgInfo.msg.contentType;
    if (contentType == MsgContentType.video) {
      type = ChatMsg.typeVideo;
    } else if (contentType == MsgContentType.voice) {
      type = ChatMsg.typeVoice;
    } else if (contentType == MsgContentType.image) {
      type = ChatMsg.typeImage;
    } else if (contentType == MsgContentType.waitAnswer) {
      type = ChatMsg.typeWaitAnswer;
    } else {
      type = ChatMsg.typeText;
    }
    var isSend = msgInfo.msg.userId == UserHelper().userId.toString();
    return ChatMsg(type: type, isSend: isSend, messageInfo: msgInfo);
  }

  void _addMsg(MsgInfo msgInfo) {
    messageList.insert(0, _messageInfoConvertChatMsg(msgInfo));
    var isPrivateChat = msgInfo.msg.isPrivateChat;
    var isNeedSubscribe = !IAPHelper().isVip && isPrivateChat;
    if (isNeedSubscribe) {
      Completer<void> completer = Completer();
      _asyncTask.syncRun(Task(
        fun: () async {
          await Future.delayed(const Duration(milliseconds: 2000));
          if (!isDispose) {
            var isImage = msgInfo.msg.contentType == MsgContentType.image;
            PageJumpUtils.toVipPage(
                isImage ? SubscribeFrom.lockPic : SubscribeFrom.lockText);
            // reportEvent(isImage ? 'c_news_lockpic' : 'c_news_locktext');
          }
        },
        complete: completer,
      ));
    }
  }

  void _updateMsg(MsgInfo msgInfo) {
    var messageList = this.messageList;
    for (var value in messageList) {
      if (value.messageInfo.msg.id == msgInfo.msg.id) {
        value.messageInfo = msgInfo;
        messageList.refresh();
        break;
      }
    }
  }

  void _removeMsg(MsgInfo msgInfo) {
    var messageList = this.messageList;
    for (var value in messageList) {
      if (value.messageInfo.msg.id == msgInfo.msg.id) {
        messageList.remove(value);
        break;
      }
    }
  }

  bool sendMsg(String content) {
    var lastMsgInfo = messageList.firstOrNull?.messageInfo;

    if (lastMsgInfo?.msg.status == MsgStatus.sending) {
      toast("Please wait for the current message to be sent successfully");
      return false;
    }

    if (!MsgReceiveHelper().isReply(lastMsgInfo)) {
      toast("Please wait for the other party's reply");
      return false;
    }

    if (ChatHelper().isNeedSubscribe()) {
      PageJumpUtils.toVipPage(SubscribeFrom.send);
      // reportEvent('t_vip_send');
      return false;
    }

    String? lastServiceMessageId = getLastServiceMsgId();
    getIt<MsgService>().sendMsg(
      content,
      sessionId: sessionId,
      lastServiceMessageId: lastServiceMessageId,
    );
    return true;
  }

  ///获取上一次的聊天ID
  String? getLastServiceMsgId() {
    String? msgId;
    var index = 0;

    ///循环查找可用的ID
    while (msgId.isNullOrEmpty &&
        messageList.isNotEmpty &&
        messageList.length > index) {
      msgId = messageList[index].messageInfo.msg.serviceMsgId;
      ++index;
    }
    return msgId;
  }

  void showReloadMsgDialog(BuildContext context, ChatMsg message) {
    showOptionDialog(
      context,
      options: ['reload'.tr, 'delete'.tr],
      onOptionClickListener: (text, index) async {
        var messageInfo = message.messageInfo;
        var msg = messageInfo.msg;
        if (index == 0) {
          await getIt<MsgService>().insertOrUpdateMsg(
            msg.content,
            sessionId: msg.sessionId,
            userId: msg.userId,
            msgId: msg.id,
            sendFailReason: msg.sendFailReason,
            serviceMsgId: msg.serviceMsgId,
            serviceNextMessageIds: msg.serviceNextMsgIds.toStringList,
            status: MsgStatus.sended,
            contentType: msg.contentType,
            isPrivateChat: msg.isPrivateChat,
            isCreate: false,
          );
          MsgReceiveHelper().startReceiveMsg(
            messageInfo,
            messageInfo.session.id,
            messageInfo.msg.serviceMsgId ?? '',
            messageInfo.msg.serviceNextMsgIds.toStringList ?? [],
          );
        } else {
          await getIt<MsgService>().deleteMsg(messageInfo);
        }

        if (index == 0) {
          sendMsg(message.messageInfo.msg.content);
        }
      },
    );
  }

  void showReplyMsgDialog(BuildContext context, ChatMsg message) {
    showOptionDialog(
      context,
      options: ['resend'.tr, 'delete'.tr],
      onOptionClickListener: (text, index) async {
        var messageInfo = message.messageInfo;
        await getIt<MsgService>().deleteMsg(messageInfo);
        if (index == 0) {
          sendMsg(message.messageInfo.msg.content);
        }
      },
    );
  }

  void jumpUserDetails() {
    Get.toNamed(
      RouteManifest.userDetailsPage,
      arguments: {
        'sessionId': sessionId,
        'roleInfo': roleInfo,
      },
    );
  }

  void clearMsg() {
    messageList.clear();
  }

  @override
  void onClose() {
    _dispose.execute();
    super.onClose();
  }
}
